#include "markAndSave.h"
#include "CvxText.h"
#include "util.h"

namespace sp::Image::Save{

void registe_markAndSave(){
    markAndSave::registe();
}

markAndSave::markAndSave(std::vector<std::string> v){ // int fps, int width, int height
    assert(v.size() == 3);
    name = "markAndSave";
    class_name = "Image-Save-markAndSave";
    this->video_ptr_head = DATA_TARGET;
    this->current_video_ptr = video_ptr_head;
    // this->path = v[0];
    fps = std::stoi(v[0]);
    width = std::stoi(v[1]);
    height = std::stoi(v[2]);
    data_type_support.push_back(std::pair<std::vector<uint8_t>, uint8_t>({MAT,STRING},UNKNOW));
}

markAndSave::markAndSave(char* video_ptr_head, int fps, int width, int height){
    name = "markAndSave";
    class_name = "Image-Save-markAndSave";
    this->video_ptr_head = video_ptr_head;
    this->current_video_ptr = video_ptr_head;
    this->fps = fps;
    this->width = width;
    this->height = height;
    data_type_support.push_back(std::pair<std::vector<uint8_t>, uint8_t>({MAT,STRING},UNKNOW));
}

markAndSave::markAndSave(){
    name = "markAndSave";
    class_name = "Image-Save-markAndSave";
    data_type_support.push_back(std::pair<std::vector<uint8_t>, uint8_t>({MAT,STRING},UNKNOW));
}

markAndSave::~markAndSave(){
    
}

void markAndSave::registe(){
    Function::Register("Image-Save-markAndSave", createObject);
    Function::Register("Image-Save-markAndSave", createObject2);
}

Function* markAndSave::createObject(std::vector<std::string> params){
    return new markAndSave(params);
}

Function* markAndSave::createObject2(){
    return new markAndSave();
}

void markAndSave::start(){

}

bool markAndSave::waitForResource(){
    return true;
}

void markAndSave::process(std::vector<std::vector<Data*>>& data_input, std::vector<Data*>& data_output){
    // 验证输入个数
    assert(batch_size != 0);
    assert(data_input.size() <= batch_size);
    assert(data_input[0].size() == 2);
    // 处理
    for(int i = 0; i < data_input.size(); i++){
        if(data_input[i][0] == DATA_END)
            break;
        // 取出图像
        Data* img = data_input[i][0];
        short app_id = img->getAppId();
        short flow_id = img->getFlowId();
        short request_id = img->getRequestId();
        // mark
        int number = data_input[i][1]->getLength();
        Data* d = data_input[i][1]->next; // d代表车牌号字符串列表
        cv::Mat* mat = new cv::Mat(img->context.mat.rows, img->context.mat.cols, CV_8UC3);
        mat->data = (uchar*)(img->context.mat.data);
        mat->datastart = mat->data;
        mat->dataend = mat->datastart + img->context.mat.rows*img->context.mat.cols*img->context.mat.channels;
        mat->datalimit = mat->dataend;
        // 画矩形表示表示检测范围
        float x_left = 0.02, x_right = 0.8;
        float y_top = 0.5, y_down = 0.95;
        int x = mat->cols*x_left, y = mat->rows*y_top;
        int width = mat->cols*(x_right - x_left);
        int height = mat->rows*(y_down - y_top);
        cv::rectangle(*mat, cv::Rect(x, y, width, height), cv::Scalar(0, 255, 0), 5, 1, 0);
        // 显示车的数量
        /** 在图像上加字符
            第一个参数为要加字符的目标函数
            第二个参数为要加的字符
            第三个参数为字体
            第四个参数为子的粗细
            第五个参数为字符的颜色 */
        // 字符的起点
        CvxText text("/home/lx/SmartPipe/build/SimSun.ttf");
        cv::Scalar size1{80, 0.5, 0.1, 0};
        text.setFont(nullptr, &size1, nullptr, 0);
        char* str = (char*)("车辆数: " + std::to_string(number)).c_str();
        wchar_t *w_str;
        Util::ToWchar(str, w_str);
        text.putText(*mat, w_str, cv::Point(mat->cols * 0.8, mat->rows * 0.1), cv::Scalar(0, 255, 0));
        // 将所有车牌号提取出来放在图片右上角
        int ii = 1; // 第ii个车牌号
        while(d){
            // 显示每个车牌号
            char* str = (char*)(d->getStr()).c_str();
            wchar_t *w_str;
            Util::ToWchar(str, w_str);
            text.putText(*mat, w_str, cv::Point(mat->cols * 0.8, mat->rows * 0.1 + ii*100), cv::Scalar(0, 255, 0));
            d = d->next;
            ii++;
        }
        // 保存到内存 / 复制到内存
        // cv::imwrite("./images/save_" + std::to_string(index) + ".png", *mat);
        // memcpy(current_video_ptr, img->context.mat.data, img->context.mat.rows*img->context.mat.cols*img->context.mat.channels);
        // current_video_ptr += img->context.mat.rows*img->context.mat.cols*img->context.mat.channels;
        // 释放内存
        if(data_input[i][0]->subRefCount() == 0){
            assert(data_input[i][0]->type == MAT);
            executor->free((char*)(data_input[i][0]->context.mat.data));
            executor->free((char*)(data_input[i][0]));
        }
        if(data_input[i][1]->subRefCount() == 0){
            Data* q = data_input[i][1]->next;
            Data* p = data_input[i][1];
            while(q){
                executor->free((char*)(p));
                p = q;
                q = q->next;
            }
            executor->free((char*)(p));
        }
        char* ptr = executor->malloc(Data_Memory);
        Data* data = new (ptr)Data(app_id, flow_id, request_id, UNKNOW);
        data_output.push_back(data);
    }
}

bool markAndSave::releaseResource(){
    return true;
}

void markAndSave::finish(){
    
}

void markAndSave::copy(Function* other){
    Function::defaultCopy(other);
    markAndSave* oth = dynamic_cast<markAndSave*>(other);
    this->video_ptr_head = oth->video_ptr_head;
    this->current_video_ptr = oth->video_ptr_head;
    this->fps = oth->fps;
    this->width = oth->width;
    this->height = oth->height;
}

};